/**
 * Copyright (c) 2006 Amgad S Youssef
 * All Rights Reserved.
 * Licensed under the Eclipse Public License - v 1.0
 * For more information see http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipsejcde.core.builder.checkers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipsejcde.core.CheckerStatus;
import org.eclipsejcde.core.IChecker;
import org.eclipsejcde.core.ICheckerStatus;
import org.eclipsejcde.core.JCDECore;

/**
 * @author Amgad S Youssef
 *
 */
public class DuplicateAIDChecker implements IChecker {

	@Override
	public ICheckerStatus[] check(IResource resource) throws CoreException {
		if (!(resource instanceof IProject)) {
			return new ICheckerStatus[] {};
		}
		IProject project = (IProject) resource;
		if (!project.hasNature(JCDECore.NATURE_ID)) {
			return new ICheckerStatus[] {};
		}
		ArrayList statusList = new ArrayList();
		IJavaProject javaProject = JavaCore.create(project);
		IPackageFragment[] packageFragments = javaProject.getPackageFragments();
		// create map and add list of packages and applets to it
		Map aidMap = new HashMap();
		for (int i = 0; i < packageFragments.length; i++) {
			if (packageFragments[i].getKind() != IPackageFragmentRoot.K_SOURCE) {
				continue;
			}
			IStatus status = JCDECore.getPackageAID(packageFragments[i]);
			if (status.getSeverity() == IStatus.OK) {
				String aid = evalAID(status.getMessage());
				List list = (List) aidMap.get(aid);
				if (list == null) {
					list = new ArrayList();
					list.add(packageFragments[i]);
					aidMap.put(aid, list);
				} else {
					list.add(packageFragments[i]);
				}
			}
			ICompilationUnit[] compilationUnits = packageFragments[i].getCompilationUnits();
			for (int j = 0; j < compilationUnits.length; j++) {
				status = JCDECore.getAppletAID(compilationUnits[j]);
				if (status.getSeverity() == IStatus.OK) {
					String aid = evalAID(status.getMessage());
					List list = (List) aidMap.get(aid);
					if (list == null) {
						list = new ArrayList();
						list.add(compilationUnits[j]);
						aidMap.put(aid, list);
					} else {
						list.add(compilationUnits[j]);
					}
				}
			}
		}
		Iterator iter = aidMap.keySet().iterator();
		while (iter.hasNext()) {
			String aidKey = (String) iter.next();
			List list = (List) aidMap.get(aidKey);
			if (list.size() > 1) {
				for (Iterator iterator = list.iterator(); iterator.hasNext();) {
					Object element = iterator.next();
					if (element instanceof IPackageFragment) {
						IPackageFragment packageFragment = (IPackageFragment) element;
						statusList.add(new CheckerStatus(IMarker.SEVERITY_WARNING, "Duplicate AID:" + aidKey, packageFragment.getResource()));
					} else if (element instanceof ICompilationUnit) {
						ICompilationUnit compilationUnit = (ICompilationUnit) element;
						statusList.add(new CheckerStatus(IMarker.SEVERITY_WARNING, "Duplicate AID:" + aidKey, compilationUnit.getResource()));
					}
				}
			}
		}
		ICheckerStatus[] checkerStatusArr = new CheckerStatus[] {};
		if (statusList.size() > 0) {
			CheckerStatus checkerStatus = new CheckerStatus(IMarker.SEVERITY_WARNING, "Duplicate AID", project);
			for (int i = 0; i < statusList.size(); i++) {
				checkerStatus.add((CheckerStatus) statusList.get(i));
			}
			checkerStatusArr = new CheckerStatus[] { checkerStatus };
		}
		return checkerStatusArr;
	}

	private String evalAID(String aid) {
		int[] aidBytes = JCDECore.parseAID(aid);
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < aidBytes.length; i++) {
			sb.append("" + aidBytes[i]);
			if (i < aidBytes.length - 1) {
				sb.append(":");
			}
		}
		return sb.toString();
	}

}
